home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
progsrc
/
ebksrc
/
eb2.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-10
|
13KB
|
556 lines
/*
eb2.cpp
8-10-91
Electronic Book
Copyright 1991
John W. Small
All rights reserved
Licensed users of FlexList may use and modify this
tool for use in their programs.
PSW / Power SoftWare
P.O. Box 10072
McLean, Virginia 22102 8072 USA
Voice: (703) 759-3838
CIS: 73757,2233
Notes: The Electronic Book was coded to demonstrate
the various uses of FlexList.
*/
#include <ctype.h>
#include <dos.h>
#include <eb1.hpp>
#include <eb2.hpp>
#include <pckey.hpp>
#include <pcput2.hpp>
#include <pcframe.hpp>
HyperLaunch::HyperLaunch(int imageX, int imageY,
const char *launch)
{
ix = imageX;
iy = imageY;
this->launch = launch;
ilen = 0;
if (!launch)
return;
for (/* no init */; ilen < MAX_HYPER_LINE &&
launch[ilen]; ilen++)
if (launch[ilen] == HYPER_LAUNCH_DELIMIT)
break;
}
void HyperLaunch::hilite(int winleft, int wintop,
int winwidth, int winheight, int attr)
{
int x, y, i, l;
if (iy < wintop)
return;
if ((y = iy - wintop + 1) > winheight)
return;
if (ix < winleft)
if (ix + ilen <= winleft)
return; // launch left of window
else {
x = 1;
i = winleft - ix;
if ((l = ilen - i) > winwidth)
l = winwidth;
}
else if ((x = ix - winleft + 1) > winwidth)
return; // launch right of window
else {
i = 0;
if (x + ilen >= winwidth)
l = winwidth - x + 1;
else
l = ilen;
}
gotoxy(x,y);
textattr(attr);
cprintf("%.*s",l,&launch[i]);
}
int HyperLaunch::match(const char *prefix, int pfLen)
{
if (pfLen <= ilen)
if (!strncmpi(prefix,launch,pfLen))
return ix+pfLen-1;
return 0;
}
Palette HyperContext::defaultP = {
0, /* monochrome or color */
svideo(BLACK,LIGHTGRAY), svideo(WHITE,BLUE),
svideo(DARKGRAY,LIGHTGRAY), svideo(LIGHTRED,BLUE),
svideo(WHITE,BLACK), svideo(BLUE,LIGHTGRAY)
};
int HyperContext::defaultTabSpacing = 8;
void HyperContext::findLinesAndLaunches()
{
int x, y, l;
unsigned inLaunch, i;
char *nline;
HyperLauncH HL;
if ((nline = context) == (char *)0)
return;
for (x = y = 1, inLaunch = i = 0; i < clen; i++) {
if (nline) {
lines.insQD(&nline);
nline = (char *)0;
}
switch(context[i]) {
case HYPER_LAUNCH_DELIMIT:
if (context[i+1] ==
HYPER_LAUNCH_DELIMIT) {
i++;
x++;
continue;
}
if (inLaunch)
inLaunch = !inLaunch;
else if ((HL = new(launches.insQD())
HyperLaunch(x,y,
&context[++i]))
!= HyperLauncH0) {
l = HL->len();
i += l;
x += l;
}
else
inLaunch = !inLaunch;
break;
case '\r':
if (context[i+1] == '\n')
i++;
case '\n':
x = 1;
y++;
nline = &context[i+1];
break;
case TAB:
while (x++ % tabSpacing)
/* null stmt */;
break;
default:
x++;
break;
}
}
}
HyperContext::HyperContext(char *context, unsigned clen,
const char *inlinks, const char *outlinks,
unsigned startRow, unsigned startColumn,
unsigned cursorRow, unsigned cursorColumn,
unsigned topicNum)
: lines(sizeof(char *)),
launches(sizeof(HyperLaunch))
{
this ->context = context;
this->inlinks = strdup(inlinks);
this->outlinks = strdup(outlinks);
this->clen = clen;
choice = 0;
setPalette();
this->startRow = startRow;
this->startColumn = startColumn;
this->cursorRow = cursorRow;
this->cursorColumn = cursorColumn;
this->topicNum = topicNum;
tabSpacing = defaultTabSpacing;
prefix[pfLen=0] = '\0';
lines.setMaxNodes(MAX_HYPER_TOPIC_LINES);
launches.setMaxNodes(MAX_HYPER_TOPIC_LAUNCHES);
findLinesAndLaunches();
}
HC_ACTIONS HyperContext::view()
{
struct text_info ti;
ScrLnBuf scrbuf;
char *nline;
int x, y, i;
unsigned pgHeight, winHeight;
unsigned oldStartColumn, oldStartRow;
unsigned char scrollAttr;
unsigned scrollTopLeft, scrollBottomRight;
unsigned oldChoice;
HyperLauncH HL;
PCF.reset();
gettextinfo(&ti);
mappalette(P);
mapvideo(NORMAL,P);
winHeight = ti.winbottom - ti.wintop + 1;
pgHeight = winHeight - 1;
scrbuf.set(mapattr(NORMAL,P),mapattr(HILITE,P),
ti.winright-ti.winleft+1,startColumn,1,'\r',
HYPER_LAUNCH_DELIMIT,tabSpacing);
if (cursorRow >= startRow + winHeight)
startRow = cursorRow - winHeight + 1;
else if (cursorRow < startRow)
startRow = cursorRow;
oldStartColumn = oldStartRow = 0;
scrollAttr = mapattr(NORMAL,P);
scrollBottomRight = ((ti.winbottom-1) << 8)
| (ti.winright-1);
scrollTopLeft = ((ti.wintop-1) << 8)
| (ti.winleft-1);
prefix[pfLen = 0] = '\0';
oldChoice = choice = 0;
while (1) {
if (pfLen) { // find typed in hyper link
choice = 0;
for (launches.mkcur(); (HL = (HyperLauncH)
launches.nextD()) != HyperLauncH0;
/* no reinit */) {
if ((x = HL->match(prefix,pfLen)) != 0) {
cursorColumn = x + 1;
choice = launches.CurNum();
cursorRow = HL->IY();
break;
}
}
if (!choice)
prefix[pfLen = 0] = '\0';
}
else if (oldChoice != choice) // find tabbed to hyper link
if ((HL = (HyperLauncH) launches.mkcur(choice))
!= HyperLauncH0) {
cursorRow = HL->IY();
cursorColumn = HL->IX();
}
if (cursorRow < startRow)
startRow = cursorRow;
else if (cursorRow >= startRow + winHeight)
startRow = cursorRow - winHeight + 1;
if (cursorColumn < scrbuf.startColumn)
scrbuf.startColumn = cursorColumn;
else if (cursorColumn >= scrbuf.startColumn
+ scrbuf.pgWidth)
scrbuf.startColumn = cursorColumn
- scrbuf.pgWidth + 1;
if (oldStartColumn != scrbuf.startColumn ||
oldStartRow != startRow) {
if (oldStartColumn == scrbuf.startColumn &&
oldStartRow &&
((((y = oldStartRow-startRow) > 0)?
y : -y) <= 1)) {
// scroll up/down and insert line.
_DX = scrollBottomRight;
_CX = scrollTopLeft;
_BH = scrollAttr;
_AX = (y > 0)? 0x0701 : 0x0601;
geninterrupt(0x10);
y = (( y > 0)? startRow : startRow
+ winHeight - 1);
if (lines.recallD(&nline,y))
scrbuf.put(nline,ti.winleft,
ti.wintop+y-startRow);
}
else {
lines.mkcur(startRow-1);
for (y = 0; y < winHeight &&
lines.nextD(&nline); y++) {
scrbuf.put(nline,
ti.winleft,ti.wintop+y);
}
while (y < winHeight)
scrbuf.put((char *)0,
ti.winleft,ti.wintop+y++);
}
oldStartColumn = scrbuf.startColumn;
oldStartRow = startRow;
}
if (!pfLen) { // find cursor moved over hyper link
choice = 0;
for (launches.mkcur(); (HL = (HyperLauncH)
launches.nextD()) != HyperLauncH0;
/* no reinit */)
if (HL->onLaunchPad(cursorColumn,cursorRow)) {
choice = launches.CurNum();
break;
}
}
if (oldChoice != choice) { // New hyper link to hilite
if ((HL = (HyperLauncH) launches.mkcur(oldChoice))
!= HyperLauncH0)
HL->hilite(scrbuf.startColumn,startRow,
scrbuf.pgWidth,winHeight,
mapattr(HILITE,P));
if ((HL = (HyperLauncH) launches.mkcur(choice))
!= HyperLauncH0)
HL->hilite(scrbuf.startColumn,startRow,
scrbuf.pgWidth,winHeight,
mapattr(SELECT,P));
oldChoice = choice;
}
startColumn = scrbuf.startColumn; // save for hyperstack
gotoxy(cursorColumn-startColumn+1,
cursorRow-startRow+1);
pfLen = 0; // get ready to erase prefix if not added to
switch (PCK.getkey()) {
case -Home:
cursorColumn = scrbuf.startColumn = 1;
break;
case -EndKey:
// compute line length;
if (lines.recallD(&nline,cursorRow)) {
scrbuf.writebuf(nline);
cursorColumn = scrbuf.eolColumn;
}
else
cursorColumn = 1;
if (cursorColumn < scrbuf.startColumn)
scrbuf.startColumn = cursorColumn;
else if (cursorColumn >=
scrbuf.startColumn + scrbuf.pgWidth)
scrbuf.startColumn = cursorColumn
- scrbuf.pgWidth + 1;
break;
case CtrlS:
case -LArr:
if (cursorColumn > 1)
if (--cursorColumn < scrbuf.startColumn)
scrbuf.startColumn = cursorColumn;
break;
case CtrlD:
case -RArr:
if (cursorColumn < MAX_HYPER_LINE)
if (++cursorColumn >=
scrbuf.startColumn + scrbuf.pgWidth)
scrbuf.startColumn = cursorColumn
- scrbuf.pgWidth + 1;
break;
case -UpArr:
if (cursorRow > 1)
if (--cursorRow < startRow)
startRow = cursorRow;
break;
case -DnArr:
if (cursorRow < lines.Nodes()) {
if (++cursorRow >= startRow + winHeight)
startRow = cursorRow - winHeight + 1;
}
else if (startRow < cursorRow)
startRow++;
break;
case CtrlA:
case -CtrlLArr:
if (lines.recallD(&nline,cursorRow)) {
scrbuf.writebuf(nline);
if (cursorColumn > scrbuf.eolColumn)
i = scrbuf.eolColumn - 1;
else
i = cursorColumn - 1;
while (i && !isalnum((char)scrbuf.buf[i-1]))
i--;
if (!i) {
if (cursorRow == 1)
break;
if (lines.recallD(&nline,cursorRow-1)) {
cursorRow--;
scrbuf.writebuf(nline);
cursorColumn = scrbuf.eolColumn;
}
break;
}
while (i && isalnum((char)scrbuf.buf[i-1]))
i--;
cursorColumn = i + 1;
}
break;
case CtrlF:
case -CtrlRArr:
lines.mkcur(cursorRow-1);
for (i = cursorColumn - 1; lines.nextD(&nline);
i = 0) {
scrbuf.writebuf(nline);
x = scrbuf.eolColumn - 1;
if (i >= x)
continue;
while (i < x && isalnum((char)scrbuf.buf[i])) i++;
if (i >= x)
break;
while (i < x && !isalnum((char)scrbuf.buf[i])) i++;
if (i < x)
break;
}
if (lines.CurNum()) {
cursorRow = lines.CurNum();
cursorColumn = i + 1;
}
break;
case -CtrlHome:
cursorRow = startRow;
break;
case -CtrlEnd:
if (startRow + winHeight - 1 > lines.Nodes())
cursorRow = lines.Nodes();
else
cursorRow = startRow + winHeight - 1;
break;
case -PgDn:
cursorRow += pgHeight;
if (cursorRow >= lines.Nodes()) {
cursorRow = lines.Nodes();
if (startRow + pgHeight > cursorRow)
break;
}
startRow += pgHeight;
if (startRow > cursorRow)
startRow = cursorRow;
break;
case -PgUp:
if (cursorRow > pgHeight)
cursorRow -= pgHeight;
else
cursorRow = 1;
if (startRow > pgHeight)
startRow -= pgHeight;
else
startRow = 1;
break;
case -CtrlPgUp:
startRow = cursorRow = 1;
break;
case -CtrlPgDn:
cursorRow = lines.Nodes();
if (cursorRow >= startRow + winHeight)
if (cursorRow > winHeight/2)
startRow = cursorRow
- winHeight/2;
else
startRow = 1;
break;
case CtrlZ: // pan down
if (startRow < lines.Nodes())
if (++startRow > cursorRow)
cursorRow = startRow;
break;
case CtrlW: // pan up
if (startRow > 1)
if (--startRow + winHeight <= cursorRow)
cursorRow = startRow + winHeight - 1;
break;
case -F1:
return HELP;
case -F3:
return LOAD;
case -F10:
case -AltT:
return TABLE_OF_CONTENTS;
case -AltF10:
case -AltI:
return INDEX;
case CR:
choice = 0;
for (launches.mkcur(); (HL = (HyperLauncH)
launches.nextD()) != HyperLauncH0;
/* no reinit */)
if (HL->onLaunchPad(cursorColumn,cursorRow)) {
choice = launches.CurNum();
return LAUNCH;
}
break;
case -AltF1:
case BACKSP:
return BACKUP;
case -ShiftF6:
return ATTR_TOGGLE;
case -F6:
return RES_TOGGLE;
case -AltX:
return EXIT;
case TAB:
if (!choice) { // find closest launch to cursor
for (launches.mkcur(); (HL = (HyperLauncH)
launches.nextD()) != HyperLauncH0;
/* no reinit */)
if ((HL->IY() > cursorRow) ||
((HL->IY() == cursorRow) &&
((HL->IX() + HL->len())
> cursorColumn)))
break;
if ((choice = launches.CurNum()) == 0)
choice = 1;
}
else if (choice < launches.Nodes())
choice++;
else
choice = 1;
break;
case -ShiftTab:
if (!choice) { // find closest launch to cursor
for (launches.mkcur(); (HL = (HyperLauncH)
launches.prevD()) != HyperLauncH0;
/* no reinit */)
if ((HL->IY() < cursorRow) ||
((HL->IY() == cursorRow) &&
(HL->IX() < cursorColumn)))
break;
if ((choice = launches.CurNum()) == 0)
choice = launches.Nodes();
}
else if (choice > 1)
choice--;
else
choice = launches.Nodes();
break;
default:
if ((pfLen = strlen(prefix)) >= MAX_HC_PREFIX - 1)
continue;
if (!isprint(PCK.ascii()))
continue;
prefix[pfLen++] = toupper(PCK.ascii());
break;
}
prefix[pfLen] = '\0';
}
return EXIT;
}
char * HyperContext::newTarget()
{
char *t;
if (!choice) return (char *)0;
t = parseLinks(outlinks);
for (unsigned i = 1; i < choice; i++)
t = parseLinks();
return t;
}
HyperContext::~HyperContext()
{
delete context;
lines.clear();
launches.clear();
delete inlinks;
delete outlinks;
}